Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


meshchatx/src/backend/bot_handler.py dff83e198e78b84ec225e53ce3ab119f598b0a01 (dff83e19) Text, 25.25 KB

T8b949e# SPDX-License-Identifier: 0BSD

Tff7b72import T7ee787contextlib
Tff7b72import T7ee787json
Tff7b72import T7ee787logging
Tff7b72import T7ee787os
Tff7b72import T7ee787re
Tff7b72import T7ee787shutil
Tff7b72import T7ee787subprocess
Tff7b72import T7ee787sys
Tff7b72import T7ee787time
Tff7b72import T7ee787uuid

Tff7b72import T7ee787RNS

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backend Tff7b72import Te6edf3bot_process Tff7b72as Te6edf3_bot_process T8b949e# noqa: F401

Te6edf3logger Tff7b72= Te6edf3loggingTff7b72.Td2a8ffgetLoggerTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.botsTa5d6ff"Tb4b4b4)

Te6edf3_LXMF_HASH_RE Tff7b72= Te6edf3reTff7b72.Td2a8ffcompileTb4b4b4(Ta5d6ffrTa5d6ff"Ta5d6ff^[0-9a-f]Tffd700{32}Ta5d6ff$Ta5d6ff"Tb4b4b4)
Te6edf3_BOT_PROCESS_MODULE Tff7b72= Ta5d6ff"Ta5d6ffmeshchatx.src.backend.bot_processTa5d6ff"
T8b949e# cx_Freeze / AppImage / macOS bundles set sys.executable to MeshChatX itself.
T8b949e# meshchat.main() dispatches this flag to runpy.run_module before argparse.
Te6edf3_MESHCHATX_RUN_MODULE_FLAG Tff7b72= Ta5d6ff"Ta5d6ff--meshchatx-run-moduleTa5d6ff"


Tff7b72class T56d364BotHandlerTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_pathTb4b4b4, Te6edf3config_managerTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffidentity_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3identity_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffconfig_manager Tff7b72= Te6edf3config_manager
Tff7b72selfTff7b72.Td2a8ffbot_reticulum_config_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexpanduserTb4b4b4(
Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffMESHCHAT_BOT_RETICULUM_CONFIG_DIRTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff~/.reticulumTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffbots_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffidentity_pathTb4b4b4, Ta5d6ff"Ta5d6ffbotsTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrunning_bots Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ffstate_file Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_dirTb4b4b4, Ta5d6ff"Ta5d6ffbots_state.jsonTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ff_load_stateTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrunner_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Tff7b72__file__Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffbot_process.pyTa5d6ff"Tb4b4b4,
Tb4b4b4)

Tf0883e@staticmethod
Tff7b72def Td2a8ff_is_frozen_executableTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tffa657boolTb4b4b4(Tffa657getattrTb4b4b4(Te6edf3sysTb4b4b4, Ta5d6ff"Ta5d6fffrozenTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ff_resolve_bot_launcherTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Return argv prefix for launching bot_process.

Frozen desktop builds set sys.executable to MeshChatX itself. Passing
a .py path as argv[1] starts another full app instance and hits the
storage lock. Those builds re-enter via --meshchatx-run-module.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_is_frozen_executableTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[
Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4,
Te6edf3_MESHCHATX_RUN_MODULE_FLAGTb4b4b4,
Te6edf3_BOT_PROCESS_MODULETb4b4b4,
Tb4b4b4]
Tff7b72return Tb4b4b4[Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4, Tff7b72selfTff7b72.Td2a8ffrunner_pathTb4b4b4]

Tff7b72def Td2a8ff_load_stateTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstate_fileTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffbots_state Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadTb4b4b4(Te6edf3fTb4b4b4)
T8b949e# Ensure all storage paths are absolute
Tff7b72for Te6edf3entry Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff" Tff7b72in Te6edf3entryTb4b4b4:
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72if Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffbot_config_dirTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffbot_config_dirTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexpanduserTb4b4b4(Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffbot_config_dirTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexpanduserTb4b4b4(Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149FileNotFoundErrorTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffbots_state Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffbots_state Tff7b72= Tb4b4b4[Tb4b4b4]

Tff7b72def Td2a8ff_save_stateTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstate_fileTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3jsonTff7b72.Td2a8ffdumpTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4, Te6edf3fTb4b4b4, Te6edf3indentTff7b72=T79c0ff2Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8fferrorTb4b4b4(Ta5d6ff"Ta5d6ffFailed to save bots state: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)

Tff7b72def Td2a8ffget_available_templatesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffechoTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffEcho BotTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffRepeats any message it receives.Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffnoteTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffNote BotTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffStore and retrieve notes using JSON storage.Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffreminderTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffReminder BotTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffSet and receive reminders using SQLite storage.Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4]

Tff7b72def Td2a8ffrestore_enabled_botsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3entry Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstart_botTb4b4b4(
Te6edf3template_idTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3nameTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3bot_idTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffwarningTb4b4b4(Ta5d6ff"Ta5d6ffFailed to restore bot Tffd700%sTa5d6ff: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3excTb4b4b4)

Tf0883e@staticmethod
Tff7b72def Td2a8ff_normalize_lxmf_hash_hexTb4b4b4(Te6edf3valueTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3valueTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657memoryviewTb4b4b4)Tb4b4b4:
Te6edf3value Tff7b72= Te6edf3valueTff7b72.Td2a8fftobytesTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657bytesTb4b4b4)Tb4b4b4:
Te6edf3h Tff7b72= Te6edf3valueTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3h Tff7b72= Tffa657strTb4b4b4(Te6edf3valueTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Te6edf3h Tff7b72= Te6edf3hTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Ta5d6ff<Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Ta5d6ff>Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3hTb4b4b4) Tff7b72!= T79c0ff32 Tff7b72or Tff7b72not Te6edf3_LXMF_HASH_RETff7b72.Td2a8ffmatchTb4b4b4(Te6edf3hTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3h

Tf0883e@staticmethod
Tff7b72def Td2a8ff_read_lxmf_address_sidecarTb4b4b4(Te6edf3storage_dirTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3storage_dirTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx_lxmf_address.txtTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3raw Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3BotHandlerTff7b72.Td2a8ff_normalize_lxmf_hash_hexTb4b4b4(Te6edf3rawTb4b4b4)

Tf0883e@staticmethod
Tff7b72def Td2a8ff_read_bot_last_errorTb4b4b4(Te6edf3storage_dirTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3storage_dirTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx_bot_last_error.txtTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3text Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tff7b72not Te6edf3textTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3max_len Tff7b72= T79c0ff1600
Tff7b72if Tffa657lenTb4b4b4(Te6edf3textTb4b4b4) Tff7b72> Te6edf3max_lenTb4b4b4:
Tff7b72return Te6edf3textTb4b4b4[Tb4b4b4:Te6edf3max_lenTb4b4b4] Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff...Ta5d6ff"
Tff7b72return Te6edf3text

Tf0883e@staticmethod
Tff7b72def Td2a8ff_subprocess_log_pathTb4b4b4(Te6edf3storage_dirTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3storage_dirTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx_bot_subprocess.logTa5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffread_subprocess_logTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4, Te6edf3max_bytesTff7b72=T79c0ff524_288Tb4b4b4)Tb4b4b4:
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break
Tff7b72if Te6edf3entry Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffUnknown bot: Tffd700{Te6edf3bot_idTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3storage_dir Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)
Te6edf3path Tff7b72= Te6edf3BotHandlerTff7b72.Td2a8ff_subprocess_log_pathTb4b4b4(Te6edf3storage_dirTb4b4b4)
Tff7b72if Tff7b72not Te6edf3pathTb4b4b4:
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6fflogTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4, Ta5d6ff"Ta5d6fftruncatedTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fftotal_bytesTa5d6ff"Tb4b4b4: T79c0ff0Tb4b4b4}
Tff7b72tryTb4b4b4:
Te6edf3total Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffgetsizeTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6fflogTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4, Ta5d6ff"Ta5d6fftruncatedTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fftotal_bytesTa5d6ff"Tb4b4b4: T79c0ff0Tb4b4b4}
Tff7b72if Te6edf3total Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6fflogTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftruncatedTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fftotal_bytesTa5d6ff"Tb4b4b4: T79c0ff0Tb4b4b4}
Te6edf3truncated Tff7b72= Te6edf3total Tff7b72> Te6edf3max_bytes
Te6edf3to_read Tff7b72= Tffa657minTb4b4b4(Te6edf3totalTb4b4b4, Te6edf3max_bytesTb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72if Te6edf3truncatedTb4b4b4:
Te6edf3fTff7b72.Td2a8ffseekTb4b4b4(Te6edf3total Tff7b72- Te6edf3to_readTb4b4b4)
Te6edf3raw Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6fflogTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4, Ta5d6ff"Ta5d6fftruncatedTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fftotal_bytesTa5d6ff"Tb4b4b4: Te6edf3totalTb4b4b4}
Te6edf3text Tff7b72= Te6edf3rawTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffreplaceTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3truncated Tff7b72and Ta5d6ff"Tffea00\nTa5d6ff" Tff7b72in Te6edf3textTb4b4b4:
Te6edf3_firstTb4b4b4, Te6edf3_sepTb4b4b4, Te6edf3rest Tff7b72= Te6edf3textTff7b72.Td2a8ffpartitionTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3text Tff7b72= Te6edf3rest Tff7b72or Te6edf3_first
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6fflogTa5d6ff"Tb4b4b4: Te6edf3textTb4b4b4, Ta5d6ff"Ta5d6fftruncatedTa5d6ff"Tb4b4b4: Te6edf3truncatedTb4b4b4, Ta5d6ff"Ta5d6fftotal_bytesTa5d6ff"Tb4b4b4: Te6edf3totalTb4b4b4}

Tff7b72def Td2a8ffget_statusTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3botsTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]

Tff7b72for Te6edf3entry Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Te6edf3bot_id Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4)
Te6edf3template Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftemplateTa5d6ff"Tb4b4b4)
Te6edf3name Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3nameTb4b4b4:
Te6edf3name Tff7b72= Ta5d6fffTa5d6ff"Tffd700{Te6edf3templateTff7b72.Td2a8fftitleTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff BotTa5d6ff" Tff7b72if Te6edf3template Tff7b72else Ta5d6ff"Ta5d6ffBotTa5d6ff"
Te6edf3pid Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4)

Te6edf3running Tff7b72= Tff7b72False
Tff7b72if Te6edf3bot_id Tff7b72in Tff7b72selfTff7b72.Td2a8ffrunning_botsTb4b4b4:
Te6edf3running Tff7b72= Tff7b72True
Tff7b72elif Te6edf3pidTb4b4b4:
Te6edf3running Tff7b72= Tff7b72selfTff7b72.Td2a8ff_is_pid_aliveTb4b4b4(Te6edf3pidTb4b4b4)

Te6edf3address_pretty Tff7b72= Tff7b72None
Te6edf3address_full Tff7b72= Tff7b72None

T8b949e# Try running instance first
Te6edf3instance Tff7b72= Tff7b72selfTff7b72.Td2a8ffrunning_botsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3bot_idTb4b4b4, Tb4b4b4{Tb4b4b4}Tb4b4b4)Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffinstanceTa5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(
Te6edf3instance
Tff7b72and Tffa657getattrTb4b4b4(Te6edf3instanceTb4b4b4, Ta5d6ff"Ta5d6ffbotTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72and Tffa657getattrTb4b4b4(Te6edf3instanceTff7b72.Td2a8ffbotTb4b4b4, Ta5d6ff"Ta5d6fflocalTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3lh Tff7b72= Te6edf3instanceTff7b72.Td2a8ffbotTff7b72.Td2a8fflocalTff7b72.Td2a8ffhash
Te6edf3address_full Tff7b72= Tb4b4b4(
Te6edf3lhTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4) Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3lhTb4b4b4, Tb4b4b4(Tffa657bytesTb4b4b4, Tffa657bytearrayTb4b4b4)Tb4b4b4) Tff7b72else Tff7b72None
Tb4b4b4)
Tff7b72if Te6edf3address_fullTb4b4b4:
Te6edf3address_full Tff7b72= Tff7b72selfTff7b72.Td2a8ff_normalize_lxmf_hash_hexTb4b4b4(Te6edf3address_fullTb4b4b4)
Tff7b72if Te6edf3address_fullTb4b4b4:
Te6edf3address_pretty Tff7b72= Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3address_fullTb4b4b4)Tb4b4b4)

T8b949e# Fallback to identity file on disk
Tff7b72if Te6edf3address_full Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3identity Tff7b72= Tff7b72selfTff7b72.Td2a8ff_load_identity_for_botTb4b4b4(Te6edf3bot_idTb4b4b4)
Tff7b72if Te6edf3identityTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3destination Tff7b72= Te6edf3RNSTff7b72.Td2a8ffDestinationTb4b4b4(
Te6edf3identityTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffOUTTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffSINGLETb4b4b4,
Ta5d6ff"Ta5d6fflxmfTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdeliveryTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3address_full Tff7b72= Tff7b72selfTff7b72.Td2a8ff_normalize_lxmf_hash_hexTb4b4b4(Te6edf3destinationTff7b72.Td2a8ffhashTb4b4b4)
Tff7b72if Te6edf3address_fullTb4b4b4:
Te6edf3address_pretty Tff7b72= Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(
Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3address_fullTb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72if Te6edf3address_full Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3address_full Tff7b72= Tff7b72selfTff7b72.Td2a8ff_read_lxmf_address_sidecarTb4b4b4(Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3address_fullTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3address_pretty Tff7b72= Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3address_fullTb4b4b4)Tb4b4b4)

Te6edf3storage_dir Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)
Te6edf3last_err Tff7b72= Tff7b72selfTff7b72.Td2a8ff_read_bot_last_errorTb4b4b4(Te6edf3storage_dirTb4b4b4)

Te6edf3botsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Te6edf3bot_idTb4b4b4,
Ta5d6ff"Ta5d6fftemplateTa5d6ff"Tb4b4b4: Te6edf3templateTb4b4b4,
Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4: Te6edf3templateTb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3nameTb4b4b4,
Ta5d6ff"Ta5d6ffaddressTa5d6ff"Tb4b4b4: Te6edf3address_prettyTb4b4b4,
Ta5d6ff"Ta5d6fflxmf_addressTa5d6ff"Tb4b4b4: Te6edf3address_fullTb4b4b4,
Ta5d6ff"Ta5d6fffull_addressTa5d6ff"Tb4b4b4: Te6edf3address_fullTb4b4b4,
Ta5d6ff"Ta5d6ffrunningTa5d6ff"Tb4b4b4: Te6edf3runningTb4b4b4,
Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4: Te6edf3pidTb4b4b4,
Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4: Te6edf3storage_dirTb4b4b4,
Ta5d6ff"Ta5d6fflast_errorTa5d6ff"Tb4b4b4: Te6edf3last_errTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffhas_lxmfyTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4,
Ta5d6ff"Ta5d6ffdetection_errorTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffrunning_botsTa5d6ff"Tb4b4b4: Tb4b4b4[Te6edf3b Tff7b72for Te6edf3b Tff7b72in Te6edf3bots Tff7b72if Te6edf3bTb4b4b4[Ta5d6ff"Ta5d6ffrunningTa5d6ff"Tb4b4b4]Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffbotsTa5d6ff"Tb4b4b4: Te6edf3botsTb4b4b4,
Tb4b4b4}

Tff7b72def Td2a8ffstart_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3template_idTb4b4b4, Te6edf3nameTff7b72=Tff7b72NoneTb4b4b4, Te6edf3bot_idTff7b72=Tff7b72NoneTb4b4b4, Te6edf3storage_dirTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e# Reuse existing entry or create new
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72if Te6edf3bot_idTb4b4b4:
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break
Tff7b72if Te6edf3entry Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3bot_id Tff7b72= Te6edf3bot_id Tff7b72or Te6edf3uuidTff7b72.Td2a8ffuuid4Tb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffhex
Te6edf3bot_storage_dir Tff7b72= Te6edf3storage_dir Tff7b72or Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_dirTb4b4b4, Te6edf3bot_idTb4b4b4)
Te6edf3bot_storage_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3bot_storage_dirTb4b4b4)
Te6edf3jailed Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jailed_bot_storage_dirTb4b4b4(Te6edf3bot_storage_dirTb4b4b4)
Tff7b72if Tff7b72not Te6edf3jailedTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffBot storage directory must be under the identity bots directoryTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3bot_storage_dir Tff7b72= Te6edf3jailed
Te6edf3entry Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Te6edf3bot_idTb4b4b4,
Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4: Te6edf3template_idTb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3name Tff7b72or Ta5d6fffTa5d6ff"Tffd700{Te6edf3template_idTff7b72.Td2a8fftitleTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff BotTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4: Te6edf3bot_storage_dirTb4b4b4,
Ta5d6ff"Ta5d6ffbot_config_dirTa5d6ff"Tb4b4b4: Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3bot_storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffbot_reticulum_config_dirTb4b4b4,
Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4,
Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ffbots_stateTff7b72.Td2a8ffappendTb4b4b4(Te6edf3entryTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3jailed Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jailed_bot_storage_dirTb4b4b4(Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3jailedTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffBot storage directory must be under the identity bots directoryTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3bot_storage_dir Tff7b72= Te6edf3jailed
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3bot_storage_dir
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3template_id
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3name Tff7b72or Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6fffTa5d6ff"Tffd700{Te6edf3template_idTff7b72.Td2a8fftitleTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff BotTa5d6ff"
Tff7b72if Tff7b72not Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffbot_config_dirTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffbot_config_dirTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3bot_storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72selfTff7b72.Td2a8ffbot_reticulum_config_dir
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72True

Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3bot_storage_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)

Te6edf3err_file Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3bot_storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx_bot_last_error.txtTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149OSErrorTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Te6edf3err_fileTb4b4b4)

Te6edf3cmd Tff7b72= Tb4b4b4[
Tff7b72*Tff7b72selfTff7b72.Td2a8ff_resolve_bot_launcherTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ff--templateTa5d6ff"Tb4b4b4,
Te6edf3template_idTb4b4b4,
Ta5d6ff"Ta5d6ff--nameTa5d6ff"Tb4b4b4,
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ff--storageTa5d6ff"Tb4b4b4,
Te6edf3bot_storage_dirTb4b4b4,
Ta5d6ff"Ta5d6ff--config-pathTa5d6ff"Tb4b4b4,
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffbot_config_dirTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ff--reticulum-config-dirTa5d6ff"Tb4b4b4,
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4]

Te6edf3subprocess_log Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3bot_storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx_bot_subprocess.logTa5d6ff"Tb4b4b4)
Te6edf3log_f Tff7b72= Tffa657openTb4b4b4(
Te6edf3subprocess_logTb4b4b4,
Ta5d6ff"Ta5d6ffaTa5d6ff"Tb4b4b4,
Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3log_fTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6fffTa5d6ff"Tffea00\nTa5d6ff--- start Tffd700{Te6edf3timeTff7b72.Td2a8ffstrftimeTb4b4b4(Ta5d6ff'Ta5d6ff%Ta5d6ffY-Ta5d6ff%Ta5d6ffm-Tffd700%dTa5d6ff Ta5d6ff%Ta5d6ffH:Ta5d6ff%Ta5d6ffM:Ta5d6ff%Ta5d6ffSTa5d6ff'Tb4b4b4)Tffd700}Ta5d6ff ---Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3log_fTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Te6edf3proc Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffPopenTb4b4b4(
Te6edf3cmdTb4b4b4,
Te6edf3cwdTff7b72=Te6edf3bot_storage_dirTb4b4b4,
Te6edf3stdoutTff7b72=Te6edf3log_fTb4b4b4,
Te6edf3stderrTff7b72=Te6edf3subprocessTff7b72.Td2a8ffSTDOUTTb4b4b4,
Te6edf3start_new_sessionTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3envTff7b72=Tb4b4b4{Tff7b72*Tff7b72*Te6edf3osTff7b72.Td2a8ffenvironTb4b4b4, Ta5d6ff"Ta5d6ffPYTHONUNBUFFEREDTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Te6edf3log_fTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72raise
Tff7b72elseTb4b4b4:
Te6edf3log_fTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)

Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3procTff7b72.Td2a8ffpid
Tff7b72selfTff7b72.Td2a8ff_save_stateTb4b4b4(Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffrunning_botsTb4b4b4[Te6edf3bot_idTb4b4b4] Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffinstanceTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffthreadTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffstop_eventTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6fftemplateTa5d6ff"Tb4b4b4: Te6edf3template_idTb4b4b4,
Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4: Te6edf3procTff7b72.Td2a8ffpidTb4b4b4,
Ta5d6ff"Ta5d6ffprocTa5d6ff"Tb4b4b4: Te6edf3procTb4b4b4,
Tb4b4b4}
Te6edf3loggerTff7b72.Td2a8ffinfoTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffStarted bot Tffd700{Te6edf3bot_idTffd700}Ta5d6ff (template: Tffd700{Te6edf3template_idTffd700}Ta5d6ff) pid=Tffd700{Te6edf3procTff7b72.Td2a8ffpidTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3bot_id

Tff7b72def Td2a8ffstop_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break
Tff7b72if Te6edf3entry Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False

Te6edf3pid Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4)
Te6edf3tracked Tff7b72= Tff7b72selfTff7b72.Td2a8ffrunning_botsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3bot_idTb4b4b4) Tff7b72or Tb4b4b4{Tb4b4b4}
Te6edf3proc Tff7b72= Te6edf3trackedTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffprocTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3pidTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3sysTff7b72.Td2a8ffplatformTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ffwinTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3proc Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3procTff7b72.Td2a8ffterminateTb4b4b4(Tb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3procTff7b72.Td2a8ffwaitTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff2Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_is_pid_aliveTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4:
Te6edf3taskkill Tff7b72= Te6edf3shutilTff7b72.Td2a8ffwhichTb4b4b4(Ta5d6ff"Ta5d6fftaskkillTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6fftaskkillTa5d6ff"
T8b949e# Process may already have exited, so suppress "not found" noise.
Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(
Tb4b4b4[Te6edf3taskkillTb4b4b4, Ta5d6ff"Ta5d6ff/PIDTa5d6ff"Tb4b4b4, Tffa657strTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff/TTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/FTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3checkTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3timeoutTff7b72=T79c0ff5Tb4b4b4,
Te6edf3stdoutTff7b72=Te6edf3subprocessTff7b72.Td2a8ffDEVNULLTb4b4b4,
Te6edf3stderrTff7b72=Te6edf3subprocessTff7b72.Td2a8ffDEVNULLTb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3osTff7b72.Td2a8ffkillpgTb4b4b4(Te6edf3pidTb4b4b4, T79c0ff15Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Te6edf3osTff7b72.Td2a8ffkillTb4b4b4(Te6edf3pidTb4b4b4, T79c0ff15Tb4b4b4)
T8b949e# brief wait
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.5Tb4b4b4)
T8b949e# optional force kill if still alive
Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_is_pid_aliveTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3osTff7b72.Td2a8ffkillpgTb4b4b4(Te6edf3pidTb4b4b4, T79c0ff9Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Te6edf3osTff7b72.Td2a8ffkillTb4b4b4(Te6edf3pidTb4b4b4, T79c0ff9Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72pass
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffwarningTb4b4b4(
Ta5d6ff"Ta5d6ffFailed to terminate bot Tffd700%sTa5d6ff pid Tffd700%sTa5d6ff: Tffd700%sTa5d6ff"Tb4b4b4,
Te6edf3bot_idTb4b4b4,
Te6edf3pidTb4b4b4,
Te6edf3excTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_reap_processTb4b4b4(Te6edf3bot_idTb4b4b4, Te6edf3pidTb4b4b4)

Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72None
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_save_stateTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3bot_id Tff7b72in Tff7b72selfTff7b72.Td2a8ffrunning_botsTb4b4b4:
Tff7b72del Tff7b72selfTff7b72.Td2a8ffrunning_botsTb4b4b4[Te6edf3bot_idTb4b4b4]
Te6edf3loggerTff7b72.Td2a8ffinfoTb4b4b4(Ta5d6ff"Ta5d6ffStopped bot Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3bot_idTb4b4b4)
Tff7b72return Tff7b72True

Tff7b72def Td2a8ffrestart_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break
Tff7b72if Te6edf3entry Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffUnknown bot: Tffd700{Te6edf3bot_idTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstop_botTb4b4b4(Te6edf3bot_idTb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffstart_botTb4b4b4(
Te6edf3template_idTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3nameTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3bot_idTff7b72=Te6edf3bot_idTb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ffupdate_bot_nameTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
Te6edf3raw Tff7b72= Tb4b4b4(Te6edf3name Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Te6edf3raw Tff7b72= Te6edf3reTff7b72.Td2a8ffsubTb4b4b4(Ta5d6ffrTa5d6ff"Ta5d6ff[Ta5d6ff\Ta5d6ffrTa5d6ff\Ta5d6ffn]+Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3rawTb4b4b4)
Tff7b72if Tff7b72not Te6edf3rawTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffname is requiredTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3rawTb4b4b4) Tff7b72> T79c0ff256Tb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffname too longTa5d6ff"Tb4b4b4)
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break
Tff7b72if Te6edf3entry Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffUnknown bot: Tffd700{Te6edf3bot_idTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3raw
Tff7b72selfTff7b72.Td2a8ff_save_stateTb4b4b4(Tb4b4b4)
Te6edf3sd Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3sdTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3cfg_dir Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffbot_config_dirTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3sdTb4b4b4, Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3cfg_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3cfg_dirTb4b4b4, Ta5d6ff"Ta5d6ffbot_display_name.txtTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3rawTb4b4b4)
Tff7b72except Tf85149OSError Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffwarningTb4b4b4(Ta5d6ff"Ta5d6ffFailed to write bot display name file: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)
Tff7b72return Tff7b72True

Tff7b72def Td2a8ffrequest_announceTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break
Tff7b72if Te6edf3entry Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffUnknown bot: Tffd700{Te6edf3bot_idTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3pid Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3pid Tff7b72or Tff7b72not Tff7b72selfTff7b72.Td2a8ff_is_pid_aliveTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffbot is not runningTa5d6ff"Tb4b4b4)
Te6edf3sd Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3sdTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffbot has no storage directoryTa5d6ff"Tb4b4b4)
Te6edf3req Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3sdTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx_request_announceTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3reqTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4)
Tff7b72except Tf85149OSError Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffwarningTb4b4b4(Ta5d6ff"Ta5d6ffFailed to write announce request: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3excTb4b4b4)
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6fffailed to write announce requestTa5d6ff"Tb4b4b4) Tff7b72from T7ee787exc
Tff7b72return Tff7b72True

Tff7b72def Td2a8ff_jailed_bot_storage_dirTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3storage_dirTb4b4b4)Tb4b4b4:
T8b949e"""Return realpath only when storage_dir is under this identity's bots dir."""
Tff7b72if Tff7b72not Te6edf3storage_dirTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3bots_root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_dirTb4b4b4)
Te6edf3real Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3storage_dirTb4b4b4)
Tff7b72if Te6edf3real Tff7b72!= Te6edf3bots_root Tff7b72and Tff7b72not Te6edf3realTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3bots_root Tff7b72+ Te6edf3osTff7b72.Td2a8ffsepTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Te6edf3real

Tff7b72def Td2a8ffdelete_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
T8b949e# Stop it first
Tff7b72selfTff7b72.Td2a8ffstop_botTb4b4b4(Te6edf3bot_idTb4b4b4)

T8b949e# Remove from state
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3iTb4b4b4, Te6edf3e Tff7b72in Tffa657enumerateTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72del Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4[Te6edf3iTb4b4b4]
Tff7b72break

Tff7b72if Te6edf3entryTb4b4b4:
T8b949e# Delete storage dir only when jailed under bots/
Te6edf3storage_dir Tff7b72= Tff7b72selfTff7b72.Td2a8ff_jailed_bot_storage_dirTb4b4b4(Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3storage_dir Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3storage_dirTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3storage_dirTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffwarningTb4b4b4(
Ta5d6ff"Ta5d6ffFailed to delete storage dir for bot Tffd700%sTa5d6ff: Tffd700%sTa5d6ff"Tb4b4b4,
Te6edf3bot_idTb4b4b4,
Te6edf3excTb4b4b4,
Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ff_save_stateTb4b4b4(Tb4b4b4)
Te6edf3loggerTff7b72.Td2a8ffinfoTb4b4b4(Ta5d6ff"Ta5d6ffDeleted bot Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3bot_idTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffget_bot_identity_pathTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break

Tff7b72if Tff7b72not Te6edf3entryTb4b4b4:
Tff7b72return Tff7b72None

Te6edf3storage_dir Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3storage_dirTb4b4b4:
Tff7b72return Tff7b72None

Te6edf3bot_config_dir Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffbot_config_dirTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3bot_config_dirTb4b4b4:
Te6edf3id_path_bot_cfg Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3bot_config_dirTb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_path_bot_cfgTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path_bot_cfg
Te6edf3id_path_lxmf_cfg Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3bot_config_dirTb4b4b4, Ta5d6ff"Ta5d6fflxmfTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_path_lxmf_cfgTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path_lxmf_cfg

Te6edf3reticulum_config_dir Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffreticulum_config_dirTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3reticulum_config_dirTb4b4b4:
Te6edf3id_path_shared Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3reticulum_config_dirTb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_path_sharedTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path_shared

T8b949e# LXMFy stores identity in the 'config' subdirectory by default
Te6edf3id_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_pathTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path

T8b949e# Fallback to direct identity file if it was moved or configured differently
Te6edf3id_path_alt Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_path_altTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path_alt

T8b949e# LXMFy may nest inside config/lxmf
Te6edf3id_path_lxmf Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflxmfTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_path_lxmfTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path_lxmf

Te6edf3id_path_lxmf_root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6fflxmfTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_path_lxmf_rootTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path_lxmf_root

Tff7b72return Tff7b72None

Tff7b72def Td2a8ff_load_identity_for_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
Te6edf3identity_path Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_bot_identity_pathTb4b4b4(Te6edf3bot_idTb4b4b4)
Tff7b72if Tff7b72not Te6edf3identity_pathTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72return Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fffrom_fileTb4b4b4(Te6edf3identity_pathTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72None

Tf0883e@staticmethod
Tff7b72def Td2a8ff_is_pid_aliveTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3pidTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72if Te6edf3sysTff7b72.Td2a8ffplatformTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ffwinTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3BotHandlerTff7b72.Td2a8ff_is_pid_alive_windowsTb4b4b4(Te6edf3pidTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3osTff7b72.Td2a8ffkillTb4b4b4(Te6edf3pidTb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72False
T8b949e# Reaped children are gone, but unreaped zombies still answer kill(0).
Tff7b72if Te6edf3sysTff7b72.Td2a8ffplatformTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6fflinuxTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff/proc/Tffd700{Te6edf3pidTffd700}Ta5d6ff/statusTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72for Te6edf3line Tff7b72in Te6edf3fTb4b4b4:
Tff7b72if Te6edf3lineTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ffState:Ta5d6ff"Tb4b4b4)Tb4b4b4:
T8b949e# Z = zombie, X/x = dead
Te6edf3state Tff7b72= Te6edf3lineTff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff"Ta5d6ff:Ta5d6ff"Tb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4[T79c0ff1Tb4b4b4]Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3stateTb4b4b4[Tb4b4b4:T79c0ff1Tb4b4b4] Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ffZTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffXTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffxTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Tff7b72break
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tff7b72True

Tf0883e@staticmethod
Tff7b72def Td2a8ff_is_pid_alive_windowsTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4:
T8b949e"""Return True only while the process is still running (not exited)."""
Tff7b72import T7ee787ctypes
Tff7b72from T7ee787ctypes Tff7b72import Te6edf3wintypes

Te6edf3kernel32 Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffwindllTff7b72.Td2a8ffkernel32
Te6edf3PROCESS_QUERY_LIMITED_INFORMATION Tff7b72= T79c0ff0x1000
Te6edf3STILL_ACTIVE Tff7b72= T79c0ff259
Te6edf3handle Tff7b72= Te6edf3kernel32Tff7b72.Td2a8ffOpenProcessTb4b4b4(
Te6edf3PROCESS_QUERY_LIMITED_INFORMATIONTb4b4b4,
Tff7b72FalseTb4b4b4,
Tffa657intTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3handleTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72tryTb4b4b4:
Te6edf3code Tff7b72= Te6edf3wintypesTff7b72.Td2a8ffDWORDTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3kernel32Tff7b72.Td2a8ffGetExitCodeProcessTb4b4b4(Te6edf3handleTb4b4b4, Te6edf3ctypesTff7b72.Td2a8ffbyrefTb4b4b4(Te6edf3codeTb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tffa657intTb4b4b4(Te6edf3codeTff7b72.Td2a8ffvalueTb4b4b4) Tff7b72== Te6edf3STILL_ACTIVE
Tff7b72finallyTb4b4b4:
Te6edf3kernel32Tff7b72.Td2a8ffCloseHandleTb4b4b4(Te6edf3handleTb4b4b4)

Tff7b72def Td2a8ff_reap_processTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4, Te6edf3pidTb4b4b4)Tb4b4b4:
Te6edf3tracked Tff7b72= Tff7b72selfTff7b72.Td2a8ffrunning_botsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3bot_idTb4b4b4) Tff7b72or Tb4b4b4{Tb4b4b4}
Te6edf3proc Tff7b72= Te6edf3trackedTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffprocTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3proc Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3procTff7b72.Td2a8ffpollTb4b4b4(Tb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3procTff7b72.Td2a8ffwaitTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff5Tb4b4b4)
Tff7b72return
Tff7b72if Tff7b72not Te6edf3pidTb4b4b4:
Tff7b72return
T8b949e# Best-effort reap when we still own the child (same parent).
Tff7b72if Tffa657hasattrTb4b4b4(Te6edf3osTb4b4b4, Ta5d6ff"Ta5d6ffwaitpidTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ChildProcessErrorTb4b4b4, Tf85149OSErrorTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffwaitpidTb4b4b4(Te6edf3pidTb4b4b4, Te6edf3osTff7b72.Td2a8ffWNOHANGTb4b4b4)

Tff7b72def Td2a8ffstop_allTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3seen Tff7b72= Tffa657setTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3bot_id Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ffrunning_botsTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3seenTff7b72.Td2a8ffaddTb4b4b4(Te6edf3bot_idTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstop_botTb4b4b4(Te6edf3bot_idTb4b4b4)
Tff7b72for Te6edf3entry Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4)Tb4b4b4:
Te6edf3bot_id Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3bot_id Tff7b72or Te6edf3bot_id Tff7b72in Te6edf3seenTb4b4b4:
Tff7b72continue
Te6edf3pid Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3pid Tff7b72and Tff7b72selfTff7b72.Td2a8ff_is_pid_aliveTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstop_botTb4b4b4(Te6edf3bot_idTb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────